package com.ics.cmsadmin.frame.api;

import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.ics.cmsadmin.frame.core.exception.ExceptionUtils;
import lombok.extern.log4j.Log4j2;
import org.jsoup.Jsoup;
import org.springframework.stereotype.Component;

@Log4j2
public final class WechatApi {

    // 基础获取accessToken
    private static final String getAccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
    // 通过code获取accessToken
    private static final String getAccessTokenByCodeUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
    // 通过refreshToken获取accessToken
    private static final String refreshAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s";
    // 通过accessToken获取用户信息
    private static final String userinfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN";
    //通过基础accessToken获取详细用户信息
    private static final String newUserinfoUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN";
    // 检查accessToken是否有效
    private static final String checkAccessTokenUrl = "https://api.weixin.qq.com/sns/auth?access_token=%s&openid=%s";


    /**
     * 通过code获取accessToken
     * 正确返回数据:
     * {
     *      "access_token":"ACCESS_TOKEN",
     *      "expires_in":7200,
     *      "refresh_token":"REFRESH_TOKEN",
     *      "openid":"OPENID",
     *      "scope":"SCOPE"
     * }
     * 错误返回数据:
     * {"errcode":40029,"errmsg":"invalid code"}
     */
    public static final WechatApiResponse getAccessTokenByCode(String appId, String secret, String code){
        return execute(String.format(getAccessTokenByCodeUrl, appId, secret, code));
    }

    public static final WechatApiResponse getAccessToken(String appId, String secret){
        return execute(String.format(getAccessTokenUrl, appId, secret));
    }

    /**
     * 通过refreshToken获取accessToken
     * 正确返回结果
     * { "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", openid":"OPENID", "scope":"SCOPE" }
     * 错误返回结果
     * {"errcode":40029,"errmsg":"invalid code"}
     */
    public static final WechatApiResponse refreshAccessToken(String appid, String refreshToken) {
        return execute(String.format(refreshAccessTokenUrl, appid, refreshToken));
    }

    /**
     * 检查accessToken是否有效
     * 正确返回数据:
     * { "errcode":0,"errmsg":"ok"}
     * 错误返回数据
     * { "errcode":40003,"errmsg":"invalid openid"}
     */
    public static final WechatApiResponse checkAccessToken(String accessToken, String openid){
        return execute(String.format(checkAccessTokenUrl, accessToken, openid));
    }

    /**
     * 获取用户信息
     * 正确返回结果
     * {
     * "openid":" OPENID"," nickname": NICKNAME,"sex":"1",
     * "province":"PROVINCE","city":"CITY","country":"COUNTRY",
     * "headimgurl":    "http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
     * "privilege":[ "PRIVILEGE1" "PRIVILEGE2" ],
     * "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
     * }
     * 错误返回结果
     * {"errcode":40003,"errmsg":" invalid openid "}
     */
    public static final WechatApiResponse getUserinfo(String accessToken, String openid){
        return execute(String.format(userinfoUrl, accessToken, openid));
    }


    public static final WechatApiResponse getSubscribeUserinfo(String accessToken, String openid){
        return execute(String.format(newUserinfoUrl, accessToken, openid));
    }

    /**
     * 检查并更新accessToken
     * @see WechatApi#checkAccessToken(String, String)
     * @see WechatApi#refreshAccessToken(String, String)
     */
    public static final WechatApiResponse checkAndRefreshAccessToken(String accessToken, String openId, String appid, String refreshToken){
        WechatApiResponse response = checkAccessToken(accessToken, openId);
        if (response == null || response.getErrcode() == 0){
            return response;
        }
        return refreshAccessToken(appid, refreshToken);
    }

    /**
     * 访问http请求
     */
    public static final WechatApiResponse execute(String url){
        try {
            log.info("请求微信api接口:" + url);
            String body = Jsoup.connect(url).ignoreContentType(true).execute().body();
            log.info("请求微信api接口返回数据:" + body);
            Gson gson = new GsonBuilder()
                .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
            return gson.fromJson(body, WechatApiResponse.class);
        }catch (Exception e){
            log.info("请求微信api接口异常:" + ExceptionUtils.collectExceptionStackMsg(e));
            return null;
        }
    }
}
